import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os
from datetime import datetime
from matplotlib.patches import Wedge

# 设置统一的视觉风格
plt.rcParams.update({
    'font.sans-serif': ['SimHei'],
    'axes.unicode_minus': False,
    'axes.facecolor': '#1A1A2E',
    'figure.facecolor': '#1A1A2E',
    'text.color': 'white',
    'xtick.color': 'white',
    'ytick.color': 'white',
    'grid.color': '#4A4A6A',
    'axes.linewidth': 1.5
})


def create_nightingale_donut_chart():
    """创建南丁格尔圆环图"""
    # 使用您提供的准确文件路径
    data_path = r"D:\大三上\大数据分析及数据可视化\《Excel数据可视化 - 从图表到数据大屏》-清华-郭宏远\实验\data\erp_order_data.xlsx"

    try:
        df = pd.read_excel(data_path)
        print(f"成功加载ERP订单数据，总记录数: {len(df)}")
    except Exception as e:
        print(f"加载数据失败: {e}")
        return

    # 按店铺分组计算订单数量
    store_data = df['store_name'].value_counts().reset_index()
    store_data.columns = ['store', 'count']

    # 取前4个店铺，确保图表清晰可读
    store_data = store_data.head(4)

    stores = store_data['store'].tolist()
    counts = store_data['count'].tolist()
    total = sum(counts)

    # 计算百分比
    percentages = [count / total for count in counts]

    # 查找订单量最多的店铺
    max_idx = np.argmax(counts)
    max_store = stores[max_idx]
    max_count = counts[max_idx]
    max_percentage = max_count / total

    # 颜色方案（从知识库中提取的正确配色）
    colors = ['#E56A72', '#FFB94F', '#4BB5C2', '#5C1E2B']

    # 创建图形
    fig = plt.figure(figsize=(14, 9), facecolor='#1A1A2E')
    ax = fig.add_subplot(111, facecolor='#1A1A2E')

    # 计算角度 - 每个店铺分配90度
    num_stores = len(stores)
    angle_per_store = 360 / num_stores
    angles = [i * angle_per_store for i in range(num_stores)]

    # 圆环参数设置
    inner_radius = 0.4  # 内半径（控制孔洞大小）
    outer_radius = 1.0  # 外半径
    width = outer_radius - inner_radius  # 环宽度

    # 创建每个店铺的扇区
    for i in range(num_stores):
        start_angle = angles[i]
        end_angle = angles[i] + angle_per_store
        # 使用Wedge创建圆环扇区
        wedge = Wedge(
            center=(0, 0),
            r=outer_radius,
            theta1=start_angle,
            theta2=end_angle,
            width=width,
            facecolor=colors[i],
            edgecolor='white',
            linewidth=1.5,
            alpha=0.9
        )
        ax.add_patch(wedge)

        # 计算标签位置
        mid_angle = (start_angle + end_angle) / 2
        label_radius = outer_radius * 0.8

        # 转换极坐标为笛卡尔坐标（-90度调整为从顶部开始）
        x = label_radius * np.cos(np.radians(mid_angle - 90))
        y = label_radius * np.sin(np.radians(mid_angle - 90))

        # 根据位置确定标签对齐方式
        ha = 'left' if x >= 0 else 'right'
        va = 'bottom' if y >= 0 else 'top'

        # 添加店铺名称和百分比
        label_text = f"{stores[i]}\n{percentages[i]:.1%}"
        ax.text(
            x, y, label_text,
            ha=ha, va=va, fontsize=14, fontweight='bold', color='white',
            bbox=dict(
                boxstyle='round,pad=0.3',
                facecolor=colors[i],
                edgecolor='none',
                alpha=0.8
            )
        )

        # 添加引出线
        line_length = 0.15
        line_x = (outer_radius * 0.9) * np.cos(np.radians(mid_angle - 90))
        line_y = (outer_radius * 0.9) * np.sin(np.radians(mid_angle - 90))
        end_x = (outer_radius + line_length) * np.cos(np.radians(mid_angle - 90))
        end_y = (outer_radius + line_length) * np.sin(np.radians(mid_angle - 90))

        # 绘制引出线
        ax.plot([line_x, end_x], [line_y, end_y], 'w-', linewidth=1.2)
        # 添加末端小点
        ax.plot(end_x, end_y, 'o', color='white', markersize=4)

        # 添加延伸线
        extend_length = 0.25
        extend_x = (outer_radius + line_length + extend_length) * np.cos(np.radians(mid_angle - 90))
        extend_y = (outer_radius + line_length + extend_length) * np.sin(np.radians(mid_angle - 90))
        ax.plot([end_x, extend_x], [end_y, extend_y], 'w-', linewidth=1.2)

    # 添加标题
    ax.set_title(
        '2022年上半年各店铺订单量分布',
        fontsize=24, fontweight='bold', pad=30, color='white'
    )

    # 添加副标题
    ax.text(
        0.5, 0.85,
        f'总订单数{total}，{max_store}订单量最多{max_count}，占比{max_percentage:.1%}',
        ha='center', va='center', transform=ax.transAxes,
        fontsize=18, color='#E0E0E0', fontweight='bold'
    )

    # 添加数据来源
    current_date = datetime.now().strftime('%Y.%m.%d')
    ax.text(
        0.5, 0.05,
        f'*注：数据来源于ERP订单系统，统计日期截至{current_date}',
        ha='center', va='center', transform=ax.transAxes,
        fontsize=12, color='#B0B0B0', alpha=0.7
    )

    # 设置坐标轴范围，确保所有内容可见
    ax.set_xlim(-outer_radius - 0.5, outer_radius + 0.5)
    ax.set_ylim(-outer_radius - 0.5, outer_radius + 0.5)

    # 隐藏坐标轴
    ax.axis('off')

    # 确保布局紧凑
    plt.tight_layout(rect=[0, 0.05, 1, 0.95])

    # 保存图片
    output_dir = r'D:\大三上\大数据分析及数据可视化\《Excel数据可视化 - 从图表到数据大屏》-清华-郭宏远\实验\results'
    os.makedirs(output_dir, exist_ok=True)
    output_path = os.path.join(output_dir, '20_南丁格尔圆环图.png')
    plt.savefig(
        output_path,
        dpi=300,
        bbox_inches='tight',
        facecolor='#1A1A2E',
        edgecolor='none'
    )

    plt.show()

    # 数据分析输出
    print("\n南丁格尔圆环图数据分析：")
    print(f"- 总订单数量：{total}")
    print(f"- 订单量最多的店铺：{max_store}（{max_count}单）")
    print(f"- 各店铺订单分布：")
    for store, count, pct in zip(stores, counts, percentages):
        print(f"  · {store}: {count}单 ({pct:.1%})")


if __name__ == "__main__":
    create_nightingale_donut_chart()